package busuanzi.module;


import busuanzi.storage.MongoClient;
import busuanzi.util.Sugars;
import org.bson.Document;
import sardine.mvc.ModelAndView;
import sardine.mvc.freemarker.FreeMarkerEngine;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import static busuanzi.storage.MongoClient.s;
import static busuanzi.util.Strings2.hasEmpty;
import static com.google.common.base.Strings.isNullOrEmpty;
import static sardine.Sardine.*;

/**
 * Auth: bruce-sha
 * Date: 2015/4/29
 */
public abstract class Administrations {

    public static void run() {

        before("/manage/*", (request, response) -> {

            String userName = request.cookie(Securities.SECURITY_USER_NAME);
            String serialNumber = request.cookie(Securities.SECURITY_SERIAL_NUMBER);
            String busuanziToken = request.cookie(Securities.SECURITY_TOKEN);

            if (hasEmpty(userName, serialNumber, busuanziToken)) {
                response.redirect("/signin.html");
                halt("未登录");
            }

            MongoClient.collection("busuanzi/token").wash(tokens -> {
                final long now = System.currentTimeMillis();
                final Document token = tokens.find(s("{un: '%s', sn: '%s',tn: '%s'}", userName, serialNumber, busuanziToken)).first();
                if (token == null || token.getLong("expirationTime") < now) response.redirect("/signin.html");
//                } else {
//                    tokens.updateOne(s("{un: '%s', sn: '%s',tn: '%s'}", userName, serialNumber, busuanziToken),
//                            s("{$set: {expirationTime: %s}, $currentDate: {LastUpdateTime: true}}", now + Securities.SECURITY_MAX_AGE));
//                }
            });
        });


        get("/manage/sites", "text/html", (request, response) -> {

            final Optional<String> querySite = Optional.ofNullable(request.queryParams("site"));

            final String userName = request.cookie(Securities.SECURITY_USER_NAME);
            final String serialNumber = request.cookie(Securities.SECURITY_SERIAL_NUMBER);

            List<String> sites = MongoClient.collection("busuanzi/user_site").bath(usersites ->
                            usersites.find(s("{username: '%s'}", userName))
                                    .projection(s("{site: 1}"))
                                    .map(document -> document.getString("site"))
                                    .into(new ArrayList<String>())
            );

            if (sites.isEmpty())
                return ModelAndView.view("manage/add_site.ftl").model("verifyId", serialNumber);

            String currentQuerySite = querySite.orElse(sites.stream().findFirst().get());

            List<SiteDetailVO> siteDetailVOList = MongoClient.collection("busuanzi/busuan").bath(busuans ->
                            busuans.find(s("{host: '%s'}", currentQuerySite))
                                    .sort(s("{path: -1}"))
                                    .projection(s("{path: 1, count: 1, lastModified: 1}"))
                                    .map(document -> new SiteDetailVO(
                                            document.getString("path"),
                                            Long.valueOf(document.getOrDefault("count", "0").toString()),
                                            document.getDate("lastModified")))
                                    .into(new ArrayList<SiteDetailVO>())
            );

            return ModelAndView
                    .view("manage/site_detail.ftl")
                    .model("username", userName)
                    .model("currentSite", currentQuerySite)
                    .model("sites", sites)
                    .model("siteDetailVOList", siteDetailVOList);

        }, new FreeMarkerEngine());


//        get("/manage/sites/:site", "text/html", (request, response) -> {
//            final String site = request.params("site");
//            List<SiteDetailVO> siteDetailVOList = MongoClient.bath("busuanzi/busuan", busuans -> busuans
//                    .find(s("{host: '%s'}", site))
//                    .sort(s("{path: -1}"))
//                    .projection(s("{path: 1, count: 1, lastModified: 1}"))
//                    .map(new Function<Document, SiteDetailVO>() {
//                        @Override
//                        public SiteDetailVO apply(Document d) {
//                            return new SiteDetailVO(
//                                    d.getString("path"),
//                                    Long.valueOf(d.getOrDefault("count", "0").toString()),
//                                    d.getDate("lastModified"));
//                        }
//                    }).into(new ArrayList<SiteDetailVO>()));
//
//            Map<String, Object> models = newHashMap("currentSite", site, "sites", sites, "siteDetailVOList", siteDetailVOList);
//            return new ModelAndView(models, "manage/site_detail.ftl");
//
//        }, new FreeMarkerEngine());


        post("/manage/site/add", (request, response) -> {

            String siteURL = request.queryParams("siteURL");

            if (isNullOrEmpty(siteURL)) halt(540, "站点地址不能为空！");

//            final String busuanziToken = request.cookie("busuanziToken");

//            Document token = MongoClient.collection("busuanzi/token").bath(
//                    tokens -> tokens.find(s("{token: '%s'}", busuanziToken)).first());
//
//            String username = token.getString("username");

            final String username = request.cookie(Securities.SECURITY_USER_NAME);
//            final String busuanziToken = request.cookie(Securities.SECURITY_TOKEN);
            final String serialNumber = request.cookie(Securities.SECURITY_SERIAL_NUMBER);


            // 验证权限
//            String tokenId = token.getObjectId("_id").toHexString();
            String verifyURL = String.format("http://%s/%s.html", siteURL, serialNumber);
            try {
                final URL url = new URL(verifyURL);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(1000 * 5);
                connection.setReadTimeout(1000 * 5);
                if (connection.getResponseCode() != 200) throw new IllegalAccessException();
            } catch (Exception e) {
                halt(540, String.format("权限验证未通过：请确保 %s 可以正常访问。", verifyURL));
            }

            MongoClient.collection("busuanzi/user_site").wash(usersites ->
                    usersites.insertOne(s("{username: '%s', site: '%s'}", username, siteURL)));
            return Sugars.OK;
        });

    }

    public static class SiteDetailVO {
        String path;
        long count;
        Date lastAccessTime;

        SiteDetailVO(String path, long count, Date lastAccessTime) {
            this.path = path;
            this.count = count;
            this.lastAccessTime = lastAccessTime == null ? new Date() : lastAccessTime;
        }

        public String getPath() {
            return path;
        }

        public long getCount() {
            return count;
        }

        public Date getLastAccessTime() {
            return lastAccessTime;
        }
    }
}
